/*
 * cuadratica.c
 *
 *  Created on: 17/02/2013
 *      Author: alex
 */

#include "../headers/cuadratica.h"

long double IntCuadratica(long double Xe, long double Ye, long double Ze,
                        long double Xd, long double Yd, long double Zd,
                        long double A, long double B, long double C,
                        long double D, long double E, long double F,
                        long double G, long double H, long double J, long double K,
                        objeto_t *objeto)
{
    long double a, b, c, t1, t2, delta;
    long double Xi1, Yi1, Zi1, Xi2, Yi2, Zi2;

    a = A*Xd*Xd + B*Yd*Yd + C*Zd*Zd + 2*D*Xd*Yd + 2*E*Yd*Zd + 2*F*Xd*Zd;

    b = 2*A*Xe*Xd + 2*B*Ye*Yd + 2*C*Ze*Zd + 2*D*Xe*Yd + 2*D*Xd*Ye + 2*E*Ye*Zd + 2*E*Yd*Ze + 2*F*Xe*Zd + 2*F*Xd*Ze + 2*G*Xd + 2*H*Yd + 2*J*Zd;

    c = A*Xe*Xe + B*Ye*Ye + C*Ze*Ze + 2*D*Xe*Ye + 2*E*Ye*Ze + 2*F*Xe*Ze + 2*G*Xe + 2*H*Ye + 2*J*Ze + K;

    delta = (pow(b, 2) - 4.0 * a * c);

    if (delta < EPSILON)
  	{
  		//No hay solución, es decir, no hay intersección con el rayo
  		return -1.0;
  	}
  	else
  	{
  		t1 = ((-b - sqrt(delta)) / (2.0 * a));
  		t2 = ((-b + sqrt(delta)) / (2.0 * a));

  		//Calcula el punto de intersección con el objeto
  		Xi1 = (Xe + t1 * Xd);
  		Yi1 = (Ye + t1 * Yd);
  		Zi1 = (Ze + t1 * Zd);

  		Xi2 = (Xe + t2 * Xd);
  		Yi2 = (Ye + t2 * Yd);
  		Zi2 = (Ze + t2 * Zd);

        if ((t1 < EPSILON) && (t2 < EPSILON)) //Está detrás del ojo
  			return -1;
  		if ((t1 < EPSILON) && (t2 > EPSILON)) // t2 delante del ojo
  		{
  			//Corta el objeto y verifica que el punto sea válido
			if (Cortar(objeto,Xi2,Yi2,Zi2) == 1)
  				return t2;
  			else
  				return -1;
  		}
  		if ((t1 > EPSILON) && (t2 < EPSILON)) // t1 delante del ojo
  		{
  			//Corta el objeto y verifica que el punto sea válido
			if (Cortar(objeto,Xi1,Yi1,Zi1) == 1)
  				return t1;
  			else
  				return -1;
  		}
  		if ((t1 > EPSILON) && (t2 > EPSILON)) // Ambos delante del ojo
  		{
  			// Devuelve el más cercano al ojo
  			if (t1 < t2)
  			{
  				if (Cortar(objeto,Xi1,Yi1,Zi1) == 1)
  					return t1;
  				else if (Cortar(objeto,Xi2,Yi2,Zi2) == 1)
  					return t2;
  				else
  					return -1;
  			}
  			else
  			{
  				if (Cortar(objeto,Xi2,Yi2,Zi2) == 1)
  					return t2;
  				else if (Cortar(objeto,Xi1,Yi1,Zi1) == 1)
  					return t1;
  				else
  					return -1;
  			}
  		}
  	}
}

long double* NormalCuadratica(long double Xi, long double Yi, long double Zi,
                                long double A, long double B, long double C, long double D, long double E,
                                long double F, long double G, long double H, long double J)
{
    long double* Normal;
    long double Norma, Xn, Yn, Zn;
    Normal = (long double*)malloc(3 * sizeof(long double));
    Xn = A*Xi + D*Yi + F*Zi + G;
    Yn = D*Xi + B*Yi + E*Zi + H;
    Zn = F*Xi + E*Yi + C*Zi + J;
    Norma = sqrt(pow(Xn,2)+pow(Yn,2)+pow(Zn,2));
    Normal[0] = Xn/Norma;
    Normal[1] = Yn/Norma;
    Normal[2] = Zn/Norma;
    return Normal;
}
